#####################################################################
# Product:      KnowledgeEngine (Plone Edition)
#
# File:         MindManagerExportAccessory.py
#
# Copyright:    Copyright (c) 2005, Faulkner Technologies
#
# Author:       Brian Oliver
#
# Description:  This file defines the MindManagerExportAccessory class,
#               that provides a mechanism to export a Model into 
#               MindManager format
#
# See Also:     Accessory, Model
#####################################################################

#####################################################################
## KnowledgeEngine Library Imports
from Products.KnowledgeEngine.Common import *
from Products.KnowledgeEngine.Component import *
from Products.KnowledgeEngine.Core import *
from Products.KnowledgeEngine.Accessory import *
from Products.KnowledgeEngine.PropertyDefinition import *
from Products.KnowledgeEngine.PropertyTypes import *
from Products.KnowledgeEngine.PropertyFormats import *
from Products.KnowledgeEngine.PropertyStructures import *
from Products.KnowledgeEngine.WizardStepDefinition import *

#####################################################################
## Zope Library Imports
from Globals import InitializeClass
from AccessControl import ClassSecurityInfo
from AccessControl.Role import RoleManager
 
#####################################################################
## Python Library Imports
# (none)

#####################################################################
## MindManagerExportAccessory Class Definition
class MindManagerExportAccessory(Accessory):
    """
        An interface specifying the standard features of an Accessory
    """

    #---------------------------------------------------------------#

    #define security
    security = ClassSecurityInfo()
    security.declareObjectPublic()
    security.setDefaultAccess("allow")
        
    #---------------------------------------------------------------#

    def getIdentity(self):
        """
            ABSTRACT: Return the unique identity of the accessory
            in the Knowledge Engine
        """
        
        #typically this will be the same as the class name
        return "MindManagerExportAccessory"
        
    #---------------------------------------------------------------#
        
    def getTitle(self, genericObject):
        """
            Returns the title of the Accessory (when
            applied to the specified genericObject)
            
            RETURN TYPE: String
        """

        return "MindManager(tm) Export (XML Format)"
        
    #---------------------------------------------------------------#
        
    def getPurpose(self, genericObject):
        """
            ABSTRACT: Returns the purpose of the Accessory (when
            applied to the specified genericObject)
            
            RETURN TYPE: String
        """

        return "Exports a Model and it's components into XML format so that it can be imported into the MindManager(tm) application."
        
    #---------------------------------------------------------------#
        
    def getIconName(self, genericObject):
        """
            ABSTRACT: Returns the name of the Icon of the Accessory (when
            applied to the specified genericObject).
            
            The IconName represents the image file name that will be found using
            acquisition.
            
            RETURN TYPE: String
        """
        
        return "mindmanager.png"
        
    #---------------------------------------------------------------#
        
    def getExecuteActionDisplayName(self, genericObject):
        """
            ABSTRACT: Returns the display name for the execute action of the Accessory (when
            applied to the specified genericObject)
            
            RETURN TYPE: String
        """

        #return different action names based on the locked status of the model
        return "Export"
        
    #---------------------------------------------------------------#
        
    def isAvailableForGenericObject(self, genericObject):
        """
            Returns if the accessory is available for the 
            specified genericObject.
            
            This method is called to determine if an Accessory
            should be displayed for the specified genericObject 
            when rendering it's property editor etc.

            RETURN TYPE: Boolean
        """

        return genericObject.isInstanceOf("Model")
        
    #---------------------------------------------------------------#
        
    def getWizardStepDefinitions(self, context=None):
        """
            ABSTRACT: This method is used by this class to
            determine the actual wizard step definitions
            for the wizard
            
            RETURN: [WizardStepDefinition]
        """

        #a function to determine if an object should be selected initially in a component tree
        isInitiallySelectedFunction = lambda genericObject: genericObject.isInstanceOf("Component") or genericObject.isInstanceOf("Model")
                     
        #a function to determine if an object should be expanded initially in a component tree
        isInitiallyExpandedFunction = lambda genericObject: genericObject.isInstanceOf("Model")
                     
        wizardStep1Definition = WizardStepDefinition("Components to include in the generated MindMap", "Choose the components that you would like to appear in your MindMap.")
        wizardStep1Definition.addPropertyDefinition(PropertyDefinition(identity="components", displayName="Components For MindMap", defaultValue=[], description="Please select the components to appear in the MindMap.", propertyType=pt_NATIVE, propertyStructure=ps_LIST, propertyFormat=pf_GENERIC_OBJECT_CHOOSER, isInitiallySelectedFunction=isInitiallySelectedFunction, isInitiallyExpandedFunction=isInitiallyExpandedFunction, containerSelectionSelectsAll=true))

        wizardStep2Definition = WizardStepDefinition("Export Options", "Set the following options for your MindManager(tm) output.")
        wizardStep2Definition.addPropertyDefinition(PropertyDefinition(identity="outputIdentities", displayName="Output Component Unique Identities", defaultValue=false, description="Should component identities be output with the component titles?", propertyType=pt_BOOLEAN, propertyFormat=pf_CHECKBOX))
        wizardStep2Definition.addPropertyDefinition(PropertyDefinition(identity="searchIndices", displayName="Output Component Search Indices", defaultValue=true, description="Should component search indices be output with the component titles if defined?", propertyType=pt_BOOLEAN, propertyFormat=pf_CHECKBOX))

        return [wizardStep1Definition, wizardStep2Definition]

    #---------------------------------------------------------------#

    def generateMindManagerContentForGenericObject(self, genericObject, wizardState):
        """
            Return the mindmanager representation for the specific generic object (including children)
            using the settings in the wizard state
            
            NOTE: not for top level objects
            
            RETURN TYPE: String
        """            

        #get the components to export (identities)
        components = wizardState.getPropertyValue("components")

        result = '<ap:Topic Dirty="0000000000000001">\n'
        
        if genericObject.isContainer():
            result = result + '<ap:SubTopics>\n'
            for child in genericObject.getChildren():
                if child.getIdentity() in components:
                    result = result + self.generateMindManagerContentForGenericObject(child, wizardState)
            result = result + '</ap:SubTopics>\n'

        #generate the node title
        nodeTitle = toHTML(genericObject.getTitleOrId())

        #are we to output component identities with the component titles?
        if wizardState.getPropertyValue("outputIdentities"):
            nodeTitle = nodeTitle + " (%s)" % genericObject.getIdentity()

        #are we to ouput component search indices with the component titles?
        if wizardState.getPropertyValue("searchIndices"):
            if isinstance(genericObject, Component) and genericObject.getSearchIndex():
                nodeTitle = nodeTitle + " [Search Index: %s]" % genericObject.getSearchIndex()

        result = result + '<ap:Text Dirty="0000000000000001" PlainText="%s"\n>' % nodeTitle
        result = result + '<ap:Font />\n'
        result = result + '</ap:Text>\n'
        result = result + '<ap:NotesGroup />\n'

        result = result + '</ap:Topic>\n'
       
        return result
        
    #---------------------------------------------------------------#

    def generateMindManagerContent(self, topLevelGenericObject, wizardState):
        """
            Generate and return the xml document representing a mindmap with the specified toplevel generic object
            using the settings in the wizard state
            
            RETURN TYPE: String
        """
        
        #xml header
        result = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n'

        result = result + '<ap:Map Dirty="0000000000000001" xmlns:ap="http://schemas.mindjet.com/MindManager/Application/2003" xmlns:cor="http://schemas.mindjet.com/MindManager/Core/2003" xmlns:pri="http://schemas.mindjet.com/MindManager/Primitive/2003" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.mindjet.com/MindManager/Application/2003 http://schemas.mindjet.com/MindManager/Application/2003 http://schemas.mindjet.com/MindManager/Core/2003 http://schemas.mindjet.com/MindManager/Core/2003 http://schemas.mindjet.com/MindManager/Delta/2003 http://schemas.mindjet.com/MindManager/Delta/2003 http://schemas.mindjet.com/MindManager/Primitive/2003 http://schemas.mindjet.com/MindManager/Primitive/2003">\n'
        result = result + '<ap:OneTopic>\n'

        result = result + self.generateMindManagerContentForGenericObject(topLevelGenericObject, wizardState)

        result = result + '</ap:OneTopic>\n'
        result = result + '</ap:Map>\n'

        return result
        
    #---------------------------------------------------------------#
        
    def execute(self, genericObject, wizardState, request): 
        """
            Executes the accessory for the specified
            genericObject using the specified wizardState.
            
            OVERRIDE: This method if you require control of the
            returned HTTP response (via the request)
        """            

        #get the response from the request (weird I know, but that's where it lives in Zope)
        response = request["RESPONSE"]
        
        #set that we are exporting an xml file and that it should be downloaded
        response.setHeader("content-type", "text/xml")
        response.addHeader("content-disposition", "attachment;filename=MindManager.xml")

        #execute the accessory wizard with this object and the wizard state
        return self.generateMindManagerContent(genericObject, wizardState)

    #---------------------------------------------------------------#

    def getWizardStepFinishButtonTitle(self, wizardState, context=None):
        """
            Return the title of the finished button for the
            wizard step using the provided wizard state.
            
            By default returns 'Finish...'.  Override this
            method if you'd like something else.

            RETURN: String
        """            
        
        return "Export..."
        
    #---------------------------------------------------------------#

#####################################################################
## Class Initialisation

# Register Accessory Information with the Knowledge Engine
registerAccessory(MindManagerExportAccessory())

#####################################################################
